use js_sys::*;
use serde::*;
use wasm_bindgen::prelude::*;

use crate::{
    core::CharacterCore,
    utils::{Island, Point},
};

extern crate console_error_panic_hook;

#[wasm_bindgen(typescript_custom_section)]
const typescript_interface: &'static str = r#"
export type Matrix = number[][]
export type Island = {
    data: number[][]
    rect: number[]
    matrix: boolean[]
}
"#;

#[wasm_bindgen]
pub struct CharacterResolver {
    core: CharacterCore,
}

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(typescript_type = "Matrix")]
    pub type Matrix;

    #[wasm_bindgen(typescript_type = "Island[]")]
    pub type IslandArray;

}

#[derive(Serialize, Deserialize)]
pub struct IslandInterface {
    pub data: Vec<Point>,
    pub rect: (usize, usize, usize, usize),
    pub matrix: Vec<Vec<bool>>,
}

#[wasm_bindgen]
impl CharacterResolver {
    #[wasm_bindgen(constructor)]
    pub fn new(image_data: Vec<u8>, width: usize) -> CharacterResolver {
        console_error_panic_hook::set_once();
        let mut matrix: Vec<Vec<u8>> = Vec::new();
        for x in 0..width {
            let mut row = Vec::new();
            for y in 0..width {
                let index = (x * width + y) * 4 + 3;
                let depth = image_data[index];
                row.push(depth);
            }
            matrix.push(row);
        }
        let core = CharacterCore { width, matrix };
        return CharacterResolver { core };
    }

    pub fn get_matrix(&self) -> Matrix {
        return JsValue::from_serde(&self.core.matrix).unwrap().into();
    }

    pub fn find_islands(&self) -> IslandArray {
        let islands = self.core.find_islands();
        let island_array = Array::new();
        for data in islands {
            let rect = data.get_rect();
            let matrix = data.get_matrix();
            let island = IslandInterface { data, rect, matrix };
            let island_js = JsValue::from_serde(&island).unwrap();
            island_array.push(&island_js);
        }
        return JsValue::from(island_array).into();
    }
}
